package com.bootdo.clouddo.task;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import com.bootdo.clouddo.config.TaskConfig;
import com.bootdo.clouddo.utils.http.JuejinUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bootdo.clouddo.config.JuejinApiConfig;
import com.bootdo.clouddo.domain.juejin.CategoryDO;
import com.bootdo.clouddo.domain.juejin.LoginUserDO;
import com.bootdo.clouddo.domain.juejin.PostDO;
import com.bootdo.clouddo.domain.juejin.PostDetailDO;
import com.bootdo.clouddo.domain.juejin.TagDO;
import com.bootdo.clouddo.domain.juejin.UserDO;
import com.bootdo.clouddo.service.juejin.ICategoryService;
import com.bootdo.clouddo.service.juejin.IPostDetailService;
import com.bootdo.clouddo.service.juejin.IPostService;
import com.bootdo.clouddo.service.juejin.ITagService;
import com.bootdo.clouddo.service.juejin.IJuejinUserService;
import com.bootdo.clouddo.utils.StringUtils;

@Component
public class JuejinPostTask {

    private static final Logger logger = LoggerFactory.getLogger(JuejinPostTask.class);
    
    private Map<String, String> param = new HashMap<>();
    
    
    @Autowired
    private IPostService postService;
    
    @Autowired
    private ITagService tagService;
    
    @Autowired
    private IJuejinUserService userService;
    
    @Autowired
    private ICategoryService categoryService;
    
    @Autowired
    private IPostDetailService detailService;
    
    @Value("${juejin.email}")
    private String email;
    
    @Value("${juejin.password}")
    private String password;

	@Async("myExecutor")
	@Scheduled(fixedRate = 60000)
    public void hostSocket() {
		if(!TaskConfig.junjinTaskRun)
			return;
    	if(param.isEmpty())
    		return;
    	//拉取文章列表-时间线
    	String before = "";
    	for (int i = 0; i < 10000; i++) {
			try {
				Thread.sleep(60000);
				before = getHot(before);
			}catch (Exception e){
				e.printStackTrace();
			}

		}
    	
    }

	@Async("myExecutor")
	@Scheduled(fixedRate = 60000)
    public void timelineSocket() {
		if(!TaskConfig.junjinTaskRun)
			return;
		if(param.isEmpty())
			return;
    	//拉取文章列表-时间线
    	String before = "";
    	for (int i = 0; i < 10000; i++) {
			try {
				Thread.sleep(60000);
				before = getTimeline(before);
			}catch (Exception e){
				e.printStackTrace();
			}
		}
    	
    }
    
    public String getHot(String before) throws InterruptedException{
    	Map<String, String> params = new LinkedHashMap<>();
    	params.putAll(param);
	    params.put("src", "web");
	    params.put("limit", "50");
	    params.put("category", "all");
	    params.put("recomment", "1");
	    params.put("before", before);
    	
	    //发送Post数据并返回数据
	    JSONObject resultVo = JuejinUtils.getRequest(JuejinApiConfig.HOT_RECOMMENT + "?category=all&limit={limit}&recomment={recomment}&before={before}", params);
	    
	    if(resultVo == null || !StringUtils.equals(resultVo.getString("m"), "ok"))
	    	return null;
	    
	    JSONArray list = resultVo.getJSONObject("d").getJSONObject("entry").getJSONArray("entrylist");
	    if(list == null || list.isEmpty())
	    	return null;
	    
	    for (Object obj : list) {
	    	Thread.sleep(500);
			JSONObject json = JSONObject.parseObject(JSONObject.toJSONString(obj));
	    	PostDO post = json.toJavaObject(PostDO.class);
	    	//获取postId
	    	boolean result = savePost(post);
	    	if(result) {
	    		saveTag(post);
	    		saveCategory(post);
	    		savePostDetail(post);
	    		saveUser(post);
	    		logger.info("成功拉取一条数据:" + JSONObject.toJSONString(post));
	    	}
	    	before = json.getString("verifyCreatedAt");
		}
	    return before;
    }
    
    public String getTimeline(String before) throws InterruptedException{
    	String timelineUrl = JuejinApiConfig.TIMELINE;
    	Map<String, String> params = new LinkedHashMap<>();
    	params.putAll(param);
	    params.put("src", "web");
	    params.put("limit", "50");
	    params.put("category", "all");
	    params.put("recomment", "1");
	    params.put("before", before);
    	
	    //发送Post数据并返回数据
	    JSONObject resultVo = JuejinUtils.getRequest(timelineUrl + "?category=all&limit={limit}&recomment={recomment}&before={before}", params);
	    
	    if(resultVo == null || !StringUtils.equals(resultVo.getString("m"), "ok"))
	    	return null;
	    
	    JSONArray list = resultVo.getJSONObject("d").getJSONArray("entrylist");
	    if(list == null || list.isEmpty())
	    	return null;
	    
	    for (Object obj : list) {
	    	Thread.sleep(500);
	    	JSONObject json = JSONObject.parseObject(JSONObject.toJSONString(obj));
	    	PostDO post = json.toJavaObject(PostDO.class);
	    	//获取postId
	    	boolean result = savePost(post);
	    	if(result) {
	    		saveTag(post);
	    		saveCategory(post);
	    		savePostDetail(post);
	    		saveUser(post);
	    		logger.info("成功拉取一条数据:" + JSONObject.toJSONString(post));
	    	}
	    	before = json.getString("verifyCreatedAt");
		}
	    return before;
    }
    
    private boolean savePost(PostDO post) {
    	try {
    		//获取postId
	    	String postUrl = post.getOriginalUrl();
	    	String postId = postUrl.split("/")[postUrl.split("/").length-1];
	    	if(postId.contains("?"))
	    		postId = postId.split("\\?")[0];
	    	post.setId(postId);
	    	
    		if(postService.exists(post.getId())) {
    			//logger.info("发现重复数据:" + post.getId());
    			// System.out.print(".");
    			return false;
    		}
    		//生成用户ID
    		post.setUserId(JSONObject.parseObject(post.getUser()).getString("objectId"));
    		//生成tagIds
    		JSONArray ja = JSONArray.parseArray(post.getTags());
    		StringBuilder tagIds = new StringBuilder();
    		for (Object obj : ja) {
				tagIds.append(((JSONObject)obj).getString("id") + ",");
			}
    		if(tagIds.toString().contains(","))
    			tagIds.deleteCharAt(tagIds.length()-1);
    		post.setTagIds(tagIds.toString());
    		//生成categoryIds
    		post.setCategoryId(JSONObject.parseObject(post.getCategory()).getString("id"));
			postService.save(post);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
    }
    
    private void savePostDetail(PostDO post) {
    	try {
    		if(!post.getOriginalUrl().startsWith("https://juejin.im")) 
    			return;
    		if(detailService.get(post.getId()) != null)
    			return;
    		Map<String, String> p = new HashMap<>();
        	p.putAll(param);
        	p.put("type", "entryView");
        	p.put("postId", post.getId());
    		JSONObject resultVo = JuejinUtils.getRequest(JuejinApiConfig.DETAIL_DATA + "?type=entryView&postId={postId}", p);
    		if(resultVo == null || !StringUtils.equals(resultVo.getString("m"), "ok"))
    	    	return;
    		PostDetailDO detail = JSONObject.parseObject(JSONObject.toJSONString(resultVo.getJSONObject("d"))).toJavaObject(PostDetailDO.class);
    		detail.setId(post.getId());
    		detailService.save(detail);
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
    
    private void saveCategory(PostDO post) {
    	try {
    		CategoryDO category = JSONObject.parseObject(post.getCategory()).toJavaObject(CategoryDO.class);
    		if(categoryService.get(category.getId()) == null) {
    			categoryService.save(category);
    		}
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
    
    private void saveTag(PostDO post) {
    	try {
    		JSONArray ja = JSONArray.parseArray(post.getTags());
    		for (Object obj : ja) {
				JSONObject jo = (JSONObject)obj;
				TagDO tag = jo.toJavaObject(TagDO.class);
				if(tagService.get(tag.getId()) == null) {
					tagService.save(tag);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
    
    /**
     * 获取用户信息
     * @param post
     * @return
     */
    public UserDO saveUser(PostDO post) {
    	UserDO user = null;
    	try {
	    	JSONObject obj = JSONObject.parseObject(post.getUser());
	    	String id = obj.getString("objectId");
	    	Map<String, String> p = new HashMap<>();
	    	p.putAll(param);
	    	p.put("ids", id);
	    	p.put("cols", "objectId|username|avatar_large|avatarLarge|role|company|jobTitle|self_description|selfDescription|blogAddress|isUnitedAuthor|isAuthor|authData|totalHotIndex|postedEntriesCount|postedPostsCount|collectedEntriesCount|likedPinCount|collectionSetCount|subscribedTagsCount|followeesCount|followersCount|pinCount");
	    	//发送Post数据并返回数据
		    String resultStr = JuejinUtils.getStrRequest(JuejinApiConfig.USER_INFO + "?ids={ids}&cols={cols}", p);
		    if(StringUtils.isBlank(resultStr))
		    	return null;
		    JSONObject resultVo = JSONObject.parseObject(resultStr);
		    if(resultVo == null || !StringUtils.equals(resultVo.getString("m"), "ok"))
		    	return null;
		    user = resultVo.getJSONObject("d").getJSONObject(id).toJavaObject(UserDO.class);
		    user.setId(id);
		    if(userService.get(id) == null)
		    	userService.save(user);
    	} catch (Exception e) {
			e.printStackTrace();
		}
	    return user;
    }

	@Scheduled(fixedRate = 6000000)
    public LoginUserDO login() {
		if(!TaskConfig.junjinTaskRun)
			return null;
    	Map<String, String> params = new LinkedHashMap<>();
	    params.put("email", email);
	    params.put("password", password);

	    //发送Post数据并返回数据
	    JSONObject resultVo = JuejinUtils.sendPostRequest(JuejinApiConfig.AUTH_EMAIL, params);
	    
	    if(resultVo == null)
	    	return null;
	    
	    LoginUserDO loginUserDO = new LoginUserDO();
	    loginUserDO.setClientId(resultVo.getString("clientId"));
	    loginUserDO.setUid(resultVo.getString("userId"));
	    loginUserDO.setToken(resultVo.getString("token"));
	    //LoginUserDO loginUserDO = new LoginUserDO();
	    //loginUserDO.setClientId("1543855456708");
	    //loginUserDO.setUid("5c05289e5188257f301990ee");
	    //loginUserDO.setToken("eyJhY2Nlc3NfdG9rZW4iOiJpbG11TW1XQzF5VjB1dmt3IiwicmVmcmVzaF90b2tlbiI6InhOQ2F6ZU0xYTVHS2VlVDMiLCJ0b2tlbl90eXBlIjoibWFjIiwiZXhwaXJlX2luIjoyNTkyMDAwfQ==");
	    
	    param.put("device_id", loginUserDO.getClientId());
	    param.put("uid", loginUserDO.getUid());
	    param.put("token", loginUserDO.getToken());
	    param.put("src", "web");
	    System.out.println("获取到用户信息：" + JSONObject.toJSONString(param));
    	return loginUserDO;
    }
}
